﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Objects;
using BusinessBingo.Common;
using BusinessBingo.Common.Interfaces;
using BusinessBingo.Data.DataLoadOptions;
using BusinessBingo.Data.DataOrderOptions;
using BusinessBingo.Data.Filter;
using BusinessBingo.Data.Interfaces;

namespace BusinessBingo.Data
{
    public class EFWordRepository : EFBaseRepository, IWordRepository
    {
        public EFWordRepository(IUnitOfWork unitOfWork, IGuid portalGuid)
            : base(unitOfWork, portalGuid)
        {
        }

        public IList<Model.Word> GetItems(WordDataLoadOptions dlo, WordDataOrderOptions doo, WordFilter filter)
        {
            ObjectQuery<Word> query = this.GetQuery(dlo, doo, filter);
            IList<Word> items = query.ToList();

            IList<Model.Word> result = new List<Model.Word>();

            foreach (Word item in items)
            {
                result.Add(Mapping.MapWord(item));
            }

            return result;
        }

        public void AddItem(Model.Word item)
        {
            Data.Word word = Mapping.MapWord(item);
            word.Id = Guid.NewGuid();

            _context.Words.AddObject(word);
        }

        public ObjectQuery<Data.Word> GetQuery(WordDataLoadOptions dlo, WordDataOrderOptions doo, WordFilter filter)
        {
            ObjectQuery<Word> query = this._context.Words;
            return query.LoadWith(dlo).FilterFor(filter).OrderBy(doo);
        }

        public int GetItemsCount(WordFilter filter)
        {
            ObjectQuery<Word> query = this.GetQuery(null, null, filter);
            return query.Count();
        }
    }

    internal static class WordQueryExtensions
    {
        public static ObjectQuery<Word> FilterFor(this ObjectQuery<Word> query, WordFilter filter)
        {
            if(filter == null) return query;

            if(filter.WithId.HasValue == true)
            {
                query = (ObjectQuery<Word>)query.Where(x => x.Id == filter.WithId);
            }

            if(filter.WithLanguage.HasValue == true)
            {
                string lcid = Mapping.MapLanguage(filter.WithLanguage.Value);
                query = (ObjectQuery<Word>) query.Where(x => x.LCID.Equals(lcid));
            }

            if (filter.NumberOfWords.HasValue == true)
            {
                query = (ObjectQuery<Word>)query.Take(filter.NumberOfWords.Value);
            }

            return query;
        }

        public static ObjectQuery<Word> LoadWith(this ObjectQuery<Word> query, WordDataLoadOptions dlo)
        {
            WordDataLoadOptions sdlo = (WordDataLoadOptions)dlo;

            if (sdlo == null) return query;

            return query;
        }

        public static ObjectQuery<Word> OrderBy(this ObjectQuery<Word> query, WordDataOrderOptions doo)
        {
            if (doo == null) return query;

            if(doo.OrderType == DataOrderTypes.Random)
                query = (ObjectQuery<Word>)query.OrderBy(x => Guid.NewGuid());

            return query;
        }
    }
}